#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// int main()
// {
//     // 无法修改的原因是：
//     // 页表在虚拟地址和物理地址之间有着限制的作用：可让某个区域只读或可读写
//     char *str = "Hello world";
//     str[0] = 'h';
//     return 0;
// }

// // 在父进程创建子进程之后，子进程修改了全局变量，但是父进程没有任何改变，且它们的变量地址都没有改变
// // 原因：所看到的是父子进程的变量是虚拟地址，进程在页表中分别查找虚拟地址对应的物理地址进行修改
// int val = 100;
// int main()
// {
//     pid_t id = fork();
//     if(id == 0)
//     {
//         int cnt = 5;
//         // 子进程
//         while(1)
//         {
//             printf("I am child, pid : %d, ppid : %d, val : %d, &val : %p\n",getpid(),getppid(),val,&val);
//             sleep(1);
//             if(cnt) cnt--;
//             else 
//             {
//                 val = 200;
//                 printf("子进程change val : 100->200\n");
//                 cnt--; 
//             }
//         }
//     }
//     else 
//     {
//         // 父进程
//         while(1)
//         {
//             printf("I am father,pid : %d, ppid : %d, val : %d, &val : %p\n",getpid(),getppid(),val,&val);
//             sleep(1);
//         }
//     }
//     return 0;
// }

// // 地址空间中的代码区、字符常量区、全局数据区（已被初始化的全局变量和未被初始化的全局变量）、堆区、栈区
// // 栈区变量地址由下增长
// // 堆区变量地址由上增长
// int init_global = 20;
// int uninit_global;
// 
// int main()
// {
//     // 代码区
//     printf("code addr:%p\n",main);
//     const char* str = "Hello world";
//     // 字符常量区
//     printf("read only string addr:%p\n",str);
//     // 全局数据区
//     // 已初始化全局变量区
//     printf("init global value addr:%p\n",&init_global);
//     // 未初始化全局变量区
//     printf("uninit_global value addr:%p\n",&uninit_global);
//     // 堆区
//     int* mem = (int*)malloc(100);
//     int* mem1 = (int*)malloc(100);
//     printf("heap addr:%p\n",mem);
//     printf("heap addr:%p\n",mem1);
//     // 栈区
//     int a;
//     int b;
//     int c;
//     printf("stack addr:%p\n",&str);
//     printf("stack addr:%p\n",&mem);
//     printf("stack addr:%p\n",&a);
//     printf("stack addr:%p\n",&b);
//     printf("stack addr:%p\n",&c);
// 
//     return 0;
// }
